﻿using System;

namespace OverStore.Runtime.ObjectRepository.DeferredLoader
{
    /// <summary>
    /// Allows delaying actual loading of object's data.
    /// </summary>
    /// <typeparam name="TInstance">The type of the instance.</typeparam>
    public interface IDeferredLoader<TInstance> : IRuntimeComponent
        where TInstance : class
    {
        /// <summary>
        /// Gets a result indicating whether this deffered loader is active.
        /// </summary>
        /// <result>
        ///     <c>true</c> if deffered loading is enabled; otherwise, <c>false</c>, that means interoperation with <see cref="IDeferredLoader{TInstance}"/>
        ///     may be bypassed.
        /// </result>
        bool IsEnabled { get; }

        /// <summary>
        /// Checks does object wait for loading on demand, or not.
        /// </summary>
        /// <param name="instance">The instance to check for waiting for loading.</param>
        /// <returns>
        ///     <c>true</c> if <paramref name="instance"/> is waiting for loading; otherwise, <c>false</c>.
        /// </returns>
        bool IsWaitForLoading(TInstance instance);

        /// <summary>
        /// Register <paramref name="instance"/> for loading or load it immediately if delayed loading is not supported by
        /// specified object of specified implementation. Method returns <c>true</c> if instance is loaded successfuly or 
        /// if deferred loading is enabled.
        /// </summary>
        /// <param name="instance">The instance to load.</param>
        /// <param name="loadAction">Delegate that should be called when loading required.</param>
        bool LoadOrDelay(TInstance instance, Func<TInstance, bool> loadAction);
    }
}